import React from 'react'
import { Upload, Icon, Modal, message } from 'antd'
import { reqDeleteImg } from '../../api/index'
import throttle from 'lodash.throttle'
import PropTypes from 'prop-types';
import { IMG_URL } from '../../utils/constants'

function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = error => reject(error);
  });
}

export default class PicturesWall extends React.Component {

  // 声明接收父组件传递的图片数组
  static propTypes = {
    imgs: PropTypes.array
  }

  state = {
    previewVisible: false,
    previewImage: '',
    fileList: [
      // {
      //   uid: '-1',
      //   name: 'image1.png',
      //   status: 'done',
      //   url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
      // }
    ],
  };

  UNSAFE_componentWillMount() {
    const imgArr = this.props.imgs
    // 判断图片数组是否有图片，有就显示图片，没有就不显示图片

    if (imgArr && imgArr.length > 0) {
      // 更新图片到 fileList 中
      const fileList = imgArr.map((item, index) => ({
        uid: -index,
        name: item,
        status: 'done',
        url: IMG_URL + item
      })
      )
      this.setState({fileList})
    }

  }


  getImgs = () => { return this.state.fileList.map(imgs => imgs.name) }

  handleCancel = () => this.setState({ previewVisible: false });

  handlePreview = async file => {
    if (!file.url && !file.preview) {
      file.preview = await getBase64(file.originFileObj);
    }

    this.setState({
      previewImage: file.url || file.preview,
      previewVisible: true,
    });
  };

  handleChange = throttle(async ({ file, fileList }) => {
    if (file.status === 'done') {
      // 要取出 response 中的 name, url 更新或添加到当前操作对象的的name, url
      const { name, url } = file.response.data
      // 修改 fileList 的最后一个对象
      file = fileList[fileList.length - 1]
      file.name = name
      file.url = url
      message.success('图片上传成功')
    } else if (file.status === 'removed') {
      // 发送请求删除图片
      const imgName = file.name
      const result = await reqDeleteImg(imgName)
      if (result.status === 0) {
        message.success('图片删除成功')
      } else {
        message.error('图片删除失败')
      }
    }

    // 更新 存储图片的数组 fileList
    this.setState({ fileList })
  }, 2000)

  render() {
    // this.state.fileList.map(imgs => console.log(imgs.name))
    const { previewVisible, previewImage, fileList } = this.state;
    const uploadButton = (
      <div>
        <Icon type="plus" />
        <div className="ant-upload-text">Upload</div>
      </div>
    );
    return (
      <div className="clearfix">
        <Upload
          action="/manage/img/upload"
          name="image"
          listType="picture-card"
          fileList={fileList}
          onPreview={this.handlePreview}
          onChange={this.handleChange}
        >
          {fileList.length >= 8 ? null : uploadButton}
        </Upload>
        <Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
          <img alt="example" style={{ width: '100%' }} src={previewImage} />
        </Modal>
      </div>
    );
  }
}

/**
 *
 *
 * action="/manage/img/upload" // 上传图片的url
 * name="image" // 图片文件对应参数名【即后台参数的名字】
 *  listType="picture-card" // 显示风格
 * fileList={fileList} // 已上传的所有图片文件信息对象的数组
 *
 *
 *
 * 1. 熟悉内容 Upload 的内容
 * <Upload
      action="/manage/img/upload"  上传图片的url
      name="image"  图片文件对应参数名【即后台参数的名字】
      listType="picture-card"  显示风格
      fileList={fileList}  已上传的所有图片文件信息对象的数组
    >
 *
 *
 *
 * 2. fileList 在render中取
 * render() {
    const { previewVisible, previewImage, fileList } = this.state;
  }
 *
 *
 *
 *
 * 3. fileList的初始值
 * state = {
    previewVisible: false, // 标识是否显示大图预览
    previewImage: '', // 大图的url或者base64值
    fileList: [
      { // 文件信息对象 file
        uid: '-1', // 唯一标识
        name: 'xxx.png', // 文件名
        status: 'done', // 状态有：uploading done error removed
        url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', // 图片的url
      },
    ],
  };
 *
 *
 *
 *
 * 1. 熟悉 handlePreview
 * <Upload
      onPreview={this.handlePreview}
    >
 *
 *
 *
 *
 *  2. 该函数用于改变状态，控制模态框的显示和隐藏
 * handlePreview = async file => {
    this.setState({
      // 如果图片有URL就按URL显示，如果图片没有URL就按base64编码显示
      previewImage: file.url || file.preview,
      previewVisible: true,
    });
  };
 *
 *
 *
 *
 *
 *  3. 控制模态框的显示和隐藏
 * <Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
      <img alt="example" style={{ width: '100%' }} src={previewImage} />
    </Modal>
 *
 *
 *
 *
 *
 *  4. 每个 file 对应一个图片对象，图片在页面显示的是base64的编码；
 * !file.url && !file.preview   在页面中会先判断有没有 file.preview，没有才会执行base64，只会执行一次
 * handlePreview = async file => {
    if (!file.url && !file.preview) {
      file.preview = await getBase64(file.originFileObj);
    }
  };
 *
 *
 *
 * handleChange
 * 在file的状态发生改变的监听回调
  file: 当前操作(上传/删除)的file
 *
 * handleChange = async ({ file, fileList }) => {

    console.log(file.status)   有这几种状态 ： uploading done error removed

    console.log(file===fileList[fileList.length-1]) false —— file与fileList中最后一个file代表同个图片的不同对象

    console.log(file) 对象中的name的值不正确，需要存储的是response中的name；对象中没有URL，需要将response中的URL添加到对象中

    更新状态 fileList，但上传保存的图片是在file中，
    前面得到file!==fileList[fileList.length-1],
    需要重新赋值一下
    // 将数组最后一个file保存到file变量
    file = fileList[fileList.length-1]
    this.setState({ fileList })
  }
 *
 *
 *
 *
 * 一、上传图片
 * 1. 判断上传图片的状态
 * 2. 将 fileList 数组的最后一个值重新赋值给 file，让file===fileList[fileList.length - 1]
 *
 * if (file.status==='done') {
      // 将数组最后一个file保存到file变量
      file = fileList[fileList.length - 1]
      // 取出响应数据中的图片文件名和url
      const {name, url} = file.response.data
      // 保存到上传的file对象
      file.name = name
      file.url = url
 *
 * 二、删除图片
 * 1. 定义删除图片的接口
 * export const reqDeleteImg = (name) => ajax.post(BASE + '/manage/img/delete', {name})
 *
 * 2. 判断file.status的状态是否为removed，如果是发送删除图片的请求
 * else if (file.status==='removed') { // 删除
      const result = await reqDeleteImg(file.name)
      if (result.status===0) {
        message.success('删除图片成功')
      } else {
        message.error('删除图片失败')
      }
    }
 *
 *
 * 三、将数据提交到表单中（需要图片的文件名）
 *
 * picture-wall：state中的fileList包含了所有图片的文件名， 定义一个获取图片的方法
 *  getImgs=()=>this.state.fileList.map(file)=>file.img
 *
 * 此时 父组件 product-add-update 需要调用 picture-wall 子组件getImgs方法将图片的文件名
 *
 * 父组件 product-add-update 想要调子组件函数要先得到子组件对象（标签对象就是组件对象）
 *
 * 1. product-add-update在构造器中创建一个ref容器，存放到组件对象上
 * constructor(props) {
    super(props);
    // 创建ref容器, 并保存到组件对象
    this.pwRef = React.createRef()
  }
 *
 * 2. product-add-update将容器对象ref 交给 PicturesWall 标签
 * <PicturesWall ref={this.pwRef}/>
 *
 * 3. product-add-update 从容器中读取 PicturesWall 中图片数组的文件名
 * // 进行统一的表单验证
   this.props.form.validateFields(async (err, values) => {
      if (!err) {
        // 收集上传的图片文件名的数组
        const imgs = this.pwRef.current.getImgs()
        console.log('imgs', imgs)
      }
    })
 }
 *
 *
 *
 * 修改页面中显示默认的图片：父组件需要传一个product对象到picture-wall中渲染
 *
 * 1. product-add-update：
 * <PicturesWall ref={this.pwRef} imgs={this.product.imgs}/>
 *
 * 2. 子组件picture-wall声明并接收：
 *
 *static propTypes = {
    imgs: PropTypes.array
  }
 *
 *3. 将图片渲染到页面上
 *componentWillMount() {
    const imgArr = this.props.imgs
    // 判断图片数组是否有图片，有就显示图片，没有就不显示图片

    if (imgArr && imgArr.length > 0) {
      // 更新图片到 fileList 中
      const fileList = imgArr.map((item, index) => ({
        uid: -index,
        name: item,
        status: 'done',
        url: IMG_URL + item
      })
      )
      this.setState({fileList})
    }

  }
 *
 *
 *
 */